package com.atguigu.gulimall.search.service.impl;

import com.atguigu.gulimall.search.config.GulimallElasticSearchConfig;
import com.atguigu.gulimall.search.constant.EsConstant;
import com.atguigu.gulimall.search.service.MallSearchService;
import com.atguigu.gulimall.search.vo.SearchParam;
import com.atguigu.gulimall.search.vo.SearchResult;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.NestedQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;

import javax.swing.*;
import javax.swing.text.Highlighter;
import java.io.IOException;

public class MallSearchServiceImpl implements MallSearchService {

@Autowired
private RestHighLevelClient client;
    /**
     *
     *去ES检索仓鼠
     * @param param 检索的所有参数
     * @return 返回检索的结果
     */
    @Override
    public Object search(SearchParam param) {
        //1.动态构建出查询需要的DSL语句
        SearchResult result=null;
        SearchRequest searchRequest=new SearchRequest();
        try {
            //2.执行检索请求
            SearchResponse response = client.search(searchRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);
            //3.分析响应数据封装成我们需要的格式
            result=buildSearchResult(response,param);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private SearchResult buildSearchResult(SearchResponse response, SearchParam param) {
        return null;
    }

    /**
     * 准备检索请求
     * 模糊匹配。过滤（按照属性，分类，品牌，价格区间，库存）。排序，分页，高亮，聚合
     * @param
     * @return
     */
    private SearchRequest buildSearchRequest(SearchResponse response,SearchParam param) {
        //构建DSL语句
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
        /**
         * 模糊匹配。过滤（按照属性，分类，品牌，价格区间，库存）
         */
        //1.构建bool -query
        BoolQueryBuilder boolQuery= QueryBuilders.boolQuery();
        //1.1 must模糊匹配
        if(!StringUtils.isEmpty(param.getKeyword())){
            boolQuery.must(QueryBuilders.matchQuery("skuTitle",param.getKeyword()));

        }
        //1.2 bool-filter-按照三级分类ID查询
        if(param.getCatalog3Id()!=null){
            boolQuery.filter(QueryBuilders.termQuery("catalogId",param.getCatalog3Id()));
        }
        //1.3 bool-filter-按照品牌ID查询
        if(param.getBrandId()!=null&&param.getBrandId().size()>0){
            boolQuery.filter(QueryBuilders.termQuery("brandId",param.getBrandId()));
        }
        //1.3 bool-filter-按照所有指定的属性进行查询
        if(param.getAttrs()!=null&&param.getAttrs().size()>0){


            for (String attr : param.getAttrs()) {
                BoolQueryBuilder nestedQueryBuilder = QueryBuilders.boolQuery();
                String[] s=attr.split("_");
                String attrId=s[0];//检索的属性ID
                String[] attrValues = s[1].split(":");//这个属性检索用的之
                nestedQueryBuilder.must(QueryBuilders.termQuery("attr.attrId",attrId));
                nestedQueryBuilder.must(QueryBuilders.termQuery("attrs.attrValue",attrValues));
                NestedQueryBuilder nestedQuery=QueryBuilders.nestedQuery("attrs",nestedQueryBuilder, ScoreMode.None);
                boolQuery.filter(nestedQuery);
            }

        }
        //1.3 bool-filter-按照品牌ID查询
        boolQuery.filter(QueryBuilders.termQuery("hasStock",param.getHasStock()==1));
        //1.4 bool-filter-按照价格区间
        if(!StringUtils.isEmpty(param.getSkuPrice())){
            RangeQueryBuilder rangeQuery=QueryBuilders.rangeQuery("skuPrice");
            String[] s=param.getSkuPrice().split("_");
            if(s.length==2){
                //区间
                rangeQuery.gte(s[0]).lte(s[1]);
            }
            else if(s.length==1){
                if(param.getSkuPrice().startsWith(s[1])){
                    if(param.getSkuPrice().startsWith("_")){
                        rangeQuery.lte(s[0]);
                    }
                    if(param.getSkuPrice().endsWith("_")){
                        rangeQuery.gte(s[0]);
                    }
                }
            }
        }

        sourceBuilder.query(boolQuery);
        /**
         * 排序，分页，高亮
         */
        //2.1排序
        if(!StringUtils.isEmpty(param.getSort())){
            String sort= param.getSort();
            String[] s=sort.split("_");
            org.elasticsearch.search.sort.SortOrder order=s[1].equalsIgnoreCase("asc")?org.elasticsearch.search.sort.SortOrder.ASC:org.elasticsearch.search.sort.SortOrder.DESC;
            sourceBuilder.sort(s[0],order);
        }
        //2.2分页 pageSize:5
        //pageNum:1 from:0 size:5 [0,1,2,3,4]
        //pageNum:2 from:5 size:5
        //from=(pageNum-1)*size
        sourceBuilder.from((param.getPageNum()-1)*EsConstant.PRODUCT_PAGESIZE);
        sourceBuilder.size(EsConstant.PRODUCT_PAGESIZE);
        //2.3高亮
        if(!StringUtils.isEmpty(param.getKeyword())){
            HighlightBuilder builder=new HighlightBuilder();
            builder.field("skuTitle");
            builder.preTags("<b style='color:red'>");
            builder.postTags("</b>");
            sourceBuilder.highlighter(builder);
        }
        /**
         * 聚合
         */
        String s=sourceBuilder.toString();
        System.out.println("构建的DSL" + s);
        SearchRequest searchRequest=new SearchRequest(new String[]{EsConstant.PRODUCT_INDEX},sourceBuilder);

        return searchRequest;
    }
}
